#include <stdio.h>
#include <aos/kernel.h>
#include "drv_isp.h"
#include "pin_name.h" 
#include "cam_engine_api.h"
#include "cam_engine_aaa_api.h"
#include "hal/hal_api.h" 
#include "ulog/ulog.h"
#include "aos/hal/i2c.h"
#include "aos/hal/mipi_csi.h"
#include "camera_config.h"
#include "mm_config.h"
#include "drv_isp.h"
#include "cam_engine_ctrl.h"
#include "image_proc.h"
#include "iic_function.h"
#include "image_task.h"
#include "isp_function.h"
#include "isp_irq_cb.h"
#include "io.h"
#include "wrapper.h"
#include "if_v.h"

extern int g_rgbSensorCapMode;
extern int g_irSensorConvergent[];

extern volatile int g_rgb_img_ready;

static isp_handle_t handle_isp[ISP_NUM];
static isp_mi_handle_t handle_isp_mi[ISP_NUM];

volatile uint32_t ispProcFlag[ISP_NUM];
volatile uint32_t curVal[ISP_NUM];

volatile long long	mipi1_event_count = 0;
volatile int mipi1_event_flag = 0;

volatile int isp_mi_event[ISP_NUM] = {0};


volatile int isp_mode[ISP_NUM];


int isp_sw_reset(uint8_t isp_id)
{
	RSTGEN_REG_S rst_reg;

	rst_reg.vi_sw_rst_cfg.u32 = inl(CSKY_RSTGEN_BASE + VI_SW_RST_CFG);

	if(ISP_0==isp_id){
		rst_reg.vi_sw_rst_cfg.sw_isp0_rst_n = 0x1;	
	}
	else if(ISP_1==isp_id){
		rst_reg.vi_sw_rst_cfg.sw_isp1_rst_n = 0x1;	
		}	
	else if(ISP_2==isp_id){
		rst_reg.vi_sw_rst_cfg.sw_isp2_rst_n = 0x1;	
	}
	
	outl(rst_reg.cv_sw_rst_cfg.u32,CSKY_RSTGEN_BASE + VI_SW_RST_CFG);
}

int isp_sw_reset_mpw(uint8_t isp_id)
{
	uint32_t value = 0;
	uint32_t *adr = NULL;
	if(ISP_0==isp_id)
	{
		adr = (uint32_t *)0xfff21010;
		value= *adr;
		value= value&0xfffffffe;
		*adr = value;
		mdelay(10);
		value= value | 0x1;	
		*adr = value;
	}
	else if(ISP_1==isp_id)
	{
		adr = (uint32_t *)0xfff21010;
		value= *adr;
		value= value&0xfffffffef;
		*adr = value;
		mdelay(10);
		value= value | (0x1<<4);	
		*adr = value;
	}
	return 0;
}

int isp_init(int isp_id, isp_work_mode_e mode)
{
	memset(&handle_isp[isp_id], 0, sizeof(isp_handle_t));
	memset(&handle_isp_mi[isp_id], 0, sizeof(isp_mi_handle_t));
	ispProcFlag[isp_id] = 0;
	curVal[isp_id]= 0;
	isp_mi_event[isp_id] = 0;
	isp_mode[isp_id] = STREAM_MODE;
	switch(isp_id)
	{
		case ISP_0:
			handle_isp[isp_id] = drv_isp_initialize(isp_id, isp0_event_cb_fun, mode);
			if(NULL == handle_isp[isp_id])
			{
				printf("isp0 initialize failed \n");
			}
			handle_isp_mi[isp_id] = drv_isp_mi_initialize(isp_id, isp_mi0_event_cb_fun);
			if(NULL == handle_isp_mi[isp_id])
			{
				printf("isp_mipi0_initialize failed \n");
				return -1;
			}
			break;
		case ISP_1:
			handle_isp[isp_id] = drv_isp_initialize(isp_id, isp1_event_cb_fun, mode);
			if(NULL == handle_isp[isp_id])
			{
				printf("isp1 initialize failed \n");
			}
			handle_isp_mi[isp_id] = drv_isp_mi_initialize(isp_id, isp_mi1_event_cb_fun);
			if(NULL == handle_isp_mi[isp_id])
			{
				printf("isp_mipi1_initialize failed \n");
				return -1;
			}
			break;
		default: 
			printf("isp %d not support\n", isp_id);
			break;
	}
		
	return 0;
}


int isp_config(int isp_id, imageFormat_t *in, imageFormat_t *out)
{
	if((YUV422 == in->format) && (R_640x360 == out->res) && (R_720P == in->res))
	{
		cfg_isp_yuv_bypass(isp_id, in->res, out->format, true);
	}
	else if((YUV422 == in->format) && (R_720P == out->res) && (R_720P == in->res))
	{
		cfg_isp_yuv_bypass(isp_id, in->res, out->format, false);
	}
	else if((YUV422 == in->format) && (R_1080P == out->res) && (R_1080P == in->res))
	{
		cfg_isp_yuv_bypass(isp_id, in->res, out->format, false);
	}
	else if((RAW8 == in->format) && (R_640x360 == out->res) && (R_720P == in->res))
	{
		cfg_isp_raw_bypass(isp_id,in->res,out->format, true);
	}
	else if((RAW10 == in->format) && (R_640x360 == out->res) && (R_720P == in->res))
	{
		cfg_isp_raw_bypass(isp_id,in->res,out->format, true);
	}
	else if((RAW10 == in->format) && (R_720P == out->res) && (R_720P == in->res))
	{
		cfg_isp_raw_bypass(isp_id,in->res,out->format, false);
	}
	else
	{
		printf("isp_config format not support! \n");
	}
	
	isp_start(isp_id);
	return 0;
}

void isp_set_mode(int isp_id, int mode)
{
	isp_mode[isp_id] = mode;
}

int get_isp_current_mode(int isp_id)
{
	return isp_mode[isp_id];
}

void cfg_isp_base_buffer(int32_t idx, uint32_t *buffer_list, uint32_t buffer_num, uint32_t buffer_size)
{
	uint32_t temp = 0;
    uint32_t reg_mi_ctrl = 0;
    uint32_t reg_mi_imsc = 0;

    if ((buffer_num < 1) || (buffer_num > 6))
    {
        printf("Unsupport isp configuration\r\n");
    }
    
	isp_stop(idx);
    
	reg_mi_ctrl = isp_reg_read(idx, MI_CTRL);
    reg_mi_ctrl &= ~(0x7 << 11);
    reg_mi_ctrl |= (buffer_num - 1) << 11;
	isp_reg_write(idx, MI_CTRL, reg_mi_ctrl);
	temp = isp_reg_read(idx, MARVIN_CTRL_ID);
    
    isp_reg_write(idx, MI_SP_Y_SIZE, buffer_size);
	temp = isp_reg_read(idx, MARVIN_CTRL_ID);
    
	reg_mi_imsc = isp_reg_read(idx, MI_IMSC);
    reg_mi_imsc &= ~0x7e;
    for (int32_t i = 0; i < buffer_num; i++)
    {
        if (0 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD, buffer_list[i]);
        }
        else if (1 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD2, buffer_list[i]);
        }
        else if (2 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD3, buffer_list[i]);
        }
        else if (3 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD4, buffer_list[i]);
        }
        else if (4 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD5, buffer_list[i]);
        }
        else if (5 == i)
        {
            isp_reg_write(idx, MI_SP_Y_BASE_AD6, buffer_list[i]);
        }
        temp = isp_reg_read(idx, MARVIN_CTRL_ID);
        
        reg_mi_imsc |= (1 << (i + 1));
    }
	isp_reg_write(idx, MI_IMSC, reg_mi_imsc);
	temp = isp_reg_read(idx, MARVIN_CTRL_ID);

	// soft update
	//isp_reg_write(idx,MI_INIT, 0x10);
	//temp = isp_reg_read(idx, MARVIN_CTRL_ID);

    return;
}


void isp_res_crop_map(image_res_e in_res, image_res_e out_res, uint32_t *width, uint32_t *height)
{
	 if(in_res == out_res)
	{
		*width = 0;
		*height = 0;
	}
	else if((R_640x480 == in_res) && (R_640x360 == out_res))
	{
		*width = 0;
		*height = 60;
	}
	else
	{
		printf("[isp_res_crop_map]:not supper!");
	}
}

